﻿using System.IO;
using System.Linq;
using System.Xml.Linq;
using System.Xml;

namespace iTransact.Responses
{
	public static class ProcessResponse
	{
		public static Response Process(Stream httpResponse)
		{
			var response = new Response { RawXml = XDocument.Load(XmlReader.Create(new StreamReader(httpResponse))) };
			response.Status = LoadStatus(response.RawXml);
			response.Avs = LoadAvsResponse(response.RawXml);

			if (response.Status == TransactionStatus.Ok)
				response.TransactionId = response.RawXml.Descendants("XID").Single().Value;
			else
				response.ErrorMessage = response.RawXml.Descendants("ErrorMessage").Single().Value;

			return response;
		}

		static TransactionStatus LoadStatus(XDocument xml)
		{
			var element = xml.Descendants("Status").Single();
			return element.Value.ToLower() == "ok" ? TransactionStatus.Ok : TransactionStatus.Error;
		}

		static AvsResponse LoadAvsResponse(XDocument doc)
		{
			var element = doc.Descendants("AVSResponse").Single<XElement>();
			if (element.Value.ToLower() == "address")
			{
				return AvsResponse.Address;
			}
			if (element.Value.ToLower() == "address_postal")
			{
				return AvsResponse.AddressPostal;
			}
			if (element.Value.ToLower() == "address_zip5")
			{
				return AvsResponse.AddressZip5;
			}
			if (element.Value.ToLower() == "address_zip9")
			{
				return AvsResponse.AddressZip9;
			}
			if (element.Value.ToLower() == "address_ok_postal_format_error")
			{
				return AvsResponse.AddressOkPostalFormatError;
			}
			if (element.Value.ToLower() == "global_non_participant")
			{
				return AvsResponse.GlobalNonParticipant;
			}
			if (element.Value.ToLower() == "international_address_not_verified")
			{
				return AvsResponse.InternationalAddressNotVerified;
			}
			if (element.Value.ToLower() == "no_match")
			{
				return AvsResponse.NoMatch;
			}
			if (element.Value.ToLower() == "no_response")
			{
				return AvsResponse.NoResponse;
			}
			if (element.Value.ToLower() == "not_allowed")
			{
				return AvsResponse.NotAllowed;
			}
			if (element.Value.ToLower() == "postal")
			{
				return AvsResponse.Postal;
			}
			if (element.Value.ToLower() == "postal_ok_address_format_error")
			{
				return AvsResponse.PostalOKAddressFormatError;
			}
			if (element.Value.ToLower() == "service_not_supported")
			{
				return AvsResponse.ServiceNotSupported;
			}
			if (element.Value.ToLower() != "unavailable")
			{
				if (element.Value.ToLower() == "zip5")
				{
					return AvsResponse.Zip5;
				}
				if (element.Value.ToLower() == "zip9")
				{
					return AvsResponse.Zip9;
				}
			}
			return AvsResponse.Unavailable;
		}
	}
}
